perm filename XMPLES.DOC[P,JRA] blob sn#115472 filedate 1974-08-09 generic text, type C, neo UTF8
COMMENT ⊗   VALID 00009 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00002 00002	BOLTING A FROB ONTO A BEAM
C00006 00003	***** EXAMPLE 1 *****
C00010 00004	***** EXAMPLE 2 *****
C00020 00005	**RCB** my understanding of macros vs. library routines:
C00025 00006	***** EXAMPLE 3 *****
C00033 00007	      (cont)
C00041 00008	***** EXAMPLE 4 *****
C00048 00009	Experimental syntax etc. used in these examples
C00051 ENDMK
C⊗;
BOLTING A FROB ONTO A BEAM

This  is intended  to  be  a  series of  progressively  more  complex
examples  which demonstrate  some of the  features in  HAL, including
ATTACHMENT, control structure,  macros, and library routines.  All of
the examples have  essentially the same goal: bolt a  frob to a beam.
Each  example takes  into  account more  possibilities or  contains a
different way of expressing the same thing.

The initial and final attachment structures are:

        INITIAL: TABLE		      FINAL: TABLE
		    YELLOW			YELLOW
		    BLUE			BLUE
		    BEAM			BEAM
			BEAM_HOLE		    BEAM_HOLE
		    FROB			    FROB
			FROB_HOLE			FROB_HOLE
			FROB_GRASP			FROB_GRASP
		    BOLT			    BOLT

The initial structure  can be created by the  following declarations.
There will eventually be a way of interacting with the HAL monitor to
initialize frame values,  either by  reading an "object  description"
(which might have come from  the designer) or by manually positioning
the  arm at the desired positions.  There  may very well also be some
way of running  a HAL  program until it  requires an UNDEFINED  value
(for a frame,  scalar,  vector, ...) and have  the monitor prompt the
user for the desired values.

FRAME BEAM, BEAM_HOLE,      FROB, FROB_HOLE, FROB_GRASP,      BOLT;
UNITS CENTIMETERS, BOLLES, DEGREES;

BEAM ← [(30 24.2 0) : (0 0 90)];
BEAM_HOLE ← [(5.1 0 15) : (90 0 90)] WRT BEAM;
**RCB** remember that WRT is really an alternative way of saying a PREmultiply
	when it is dealing with a frame and a transform ... actually it can
	be thought of that way for vectors too:  Z WRT BEAM is equivalent
	to BEAM * Z ... or Z ∂ ORIENT(BEAM)
ATTACH BEAM_HOLE TO BEAM;
ASSERT (DEPROACH BEAM_HOLE (0 0 -3));
    COMMENT this replaces the default DEPROACH (which is (0 0 3) WRT TABLE)
	with a (0 0 -3) WRT BEAM_HOLE ... notice that the WRT is understood;
FROB ← [(20 40 0) : (0 0 90)];
FROB_HOLE ← [(5.1 2 0) : (180 0 90)] WRT FROB;
ATTACH FROB_HOLE TO FROB;
FROB_GRASP ← [(0 1.5 5) : (-90 0 0)] WRT FROB;
ATTACH FROB_GRASP TO FROB;
BOLT ← [(30 60 5) : (180 0 90)];
    COMMENT the bolt is assumed to be sticking up out of a dispenser;
***** EXAMPLE 1 *****

The task involves the following steps:
	(1) have the YELLOW arm pick up the FROB and position
	    it next to the BEAM so that the holes line up
	(2) have the BLUE arm pick up the bolt and insert
	    it in the hole (in this example it is not screwed
	    in ... a later example will use a socket driver
	    to tighten the bolt)
	(3) have both arms return to park
The FROB is assumed to be 1cm thick , and the BOLT 4cm long.

The following program is a straightforward way to express the motions
to  carry out the  task.   Everything is assumed  to be in  the right
place and virtually every motion is assumed to accomplish the desired
effect.  For example,  this  program assumes that the arm is accurate
enough  to align the FROB_HOLE  with the BEAM_HOLE  and to insert the
BOLT without hitting the side  or binding.  Later examples  will take
this type of errors into account.

OPERATE YFINGERS WITH OPENING=2;
MOVE YELLOW TO FROB_GRASP;
CENTER YELLOW;
ATTACH FROB TO YELLOW;
    COMMENT this does not have to be RIGIDLY attached because any MOVE
	no matter how it is specified (eg. MOVE FROB_HOLE ...)
	is understood to move the arm which automatically updates anything
	attached to that arm ... notice that in particular, this is
	quite different from:
		ATTACH FROB TO YELLOW;
		FROB_HOLE ← BEAM_HOLE;
	This would change the value of FROB_HOLE and the relative
	position between FROB and FROB_HOLE, but leave YELLOW and FROB
	unchanged.	
MOVE FROB_HOLE TO BEAM_HOLE;
    COMMENT notice that the FROB approaches the BEAM from the side
	(not from above) because BEAM_HOLE has a special DEPROACH
	... in this example the FROB is assumed to go right next
	to the BEAM;
OPERATE BFINGERS WITH OPENING=1;
MOVE BLUE TO BOLT;
    COMMENT assuming there is no trouble of collision;
CENTER BLUE;
MOVE BOLT TO BEAM_HOLE + (0 0 -5.3) WRT BEAM_HOLE;
    COMMENT this should position the bolt .3 centimeter off of the FROB;
MOVE BLUE TO ⊗ + (0 0 5) WRT BEAM_HOLE
    USING FREE=(X WRT BLUE), FREE=(Y WRT BLUE)
	ON FORCE(Z WRT BLUE) > 60 DO SUCCEED;
    COMMENT the arm stops when the bolt hits the bottom of the hole;

OPERATE YFINGERS WITH OPENING = 1;
DETACH FROB FROM YELLOW;
ATTACH FROB TO BEAM;
MOVE YELLOW TO YPARK;

OPERATE BFINGERS WITH OPENING = 1;
DETACH BOLT FROM BLUE;
ATTACH BOLT TO BEAM;
MOVE BLUE TO BPARK;

OUTPUT("FINISHED");
***** EXAMPLE 2 *****

This version adds a number of checks  (and some automatic recoveries)
for  possible run-time errors,  such as not  inserting the  BOLT.  It
also  utilizes  the  COBEGIN  ...    COEND  capability   to  describe
simultaneous (unordered, independent) actions.   Thus, the Yellow arm
can be picking up the FROB and positioning it near the BEAM while the
Blue arm is picking up the BOLT.  The collision avoiding is currently
the responsibility of the user.



COBEGIN
  BEGIN "PICK UP FROB BY YELLOW"
    OPERATE YFINGERS WITH OPENING=1;
    MOVE YELLOW	TO FROB_GRASP;
    CENTER YELLOW
	ON OPENING = 0 DO 
**RCB** can I qualify OPENING OF YELLOW? **RCB**
	  BEGIN "MISSED FROB"
	    STOP YELLOW;
	    SCALAR FLAG;
		COMMENT open the fingers and move away a little to give the
		    operator some room to insert the FROB;
	    OPERATE YFINGERS WITH OPENING=2;
	    GO YELLOW TO ⊗ + 3*Z;
	    OUTPUT("THE FROB IS MISSING ... POSITION IT AND TYPE `1'
		    TO TRY AGAIN");
	    READ(FLAG);
	    IF FLAG ≠ 1 THEN ABORT;
		COMMENT this stops everything, saves the world, and forces
		    the operator to deal with the problem at monitor level,
		    possibly investigating the saved information, reinitializing
		    the world to some previous state and restarting, etc;
	    GO YELLOW TO FROB_GRASP;
	    CENTER YELLOW
		ON OPENING=0 DO ABORT;  COMMENT giving up after second try;
	  END "MISSED FROB";
    ASSERT YELLOW = #(FROB_GRASP);
	COMMENT this tells the compiler that the Yellow arm can be
	    assumed to be at FROB_GRASP however control got here ...
	    possibly moving away and retrying the grasp ... currently
	    #(FROB_GRASP) is needed to specify the planning value of
	    FROB_GRASP;
    ATTACH FROB TO YELLOW;
	COMMENT at compile time this sets up the attach structure using the
	    planning values for FROB and YELLOW to determine the relative
	    position of FROB to YELLOW (ie. the transform between them)
	    ... at execution time, when the centering takes place, the
	    FROB may be slightly misplaced ... When the arm adjusts to
	    center on the FROB the attach structure remains the same, but
	    the runtime correction takes care of the difference between
	    the planned arm position and the actual position ... the effect
	    is that the FROB is assumed to be attached to the arm as planned
	    and the MOVE FROB_HOLE TO BEAM_HOLE ... statement will work
	    as planned (but the trajectory for the arm getting there is
	    slightly perturbed because it starts in a slightly different
	    place) ... If the user wants to change the relative position
	    of the FROB with respect to the arm, she has to use the
	    ATTACH FROB TO YELLOW BY T1 statement and explicitly change
	    the value of T1;
    MOVE FROB_HOLE TO BEAM_HOLE + (0 0 1.3) WRT BEAM_HOLE;
	COMMENT this positions the FROB just off of the BEAM ... the
	    next move pushes the FROB up against the BEAM;
    GO YELLOW TO ⊗ + (0 0 .5) WRT BEAM_HOLE
	ON FORCE(Z WRT BEAM_HOLE) > 50 DO SUCCEED
	ON REACHING_DESTINATION DO ABORT;
	    COMMENT give up ... what operator communication is necessary?;
		really would like a nice way of giving the operator another chance
		or a set (possibly automatically set up) of possible actions ...
		move out of the way a little and proceed ... go on a little
		farther in the same motion (expecting it  to succeed) ...;
  END "PICK UP FROB BY YELLOW";

  BEGIN "PICK UP BOLT BY BLUE"
    COMMENT meanwhile the BLUE arm can be picking up the BOLT;
    OPERATE BFINGERS WITH OPENING=1;
    MOVE BLUE TO BOLT;
    CENTER BLUE;  COMMENT assume everything is OK;
  END "PICK UP BOLT BY BLUE";
COEND;

COMMENT ... so now the FROB is positioned next to the BEAM and the BLUE arm
	is holding the BOLT;

MOVE BOLT TO BEAM_HOLE + (0 0 -5.3) WRT BEAM_HOLE; COMMENT this should
		position the bolt .3 centimeter off of the FROB;

COMMENT now begin a search just in case the BOLT doesn't immediately go in the
	hole ... it makes .2cm steps around in a spiral ... if the BOLT does not
	go in within nine tries, the whole thing is aborted;
FRAME SET; SCALAR N; COMMENT N is the number of attempts;
N ← 0;
SET ← BLUE;  COMMENT save initial arm position;
SEARCH BLUE
    INCREMENT .2;
    NORMAL_TO Z WRT BEAM_HOLE;
    REPEATING
	BEGIN "INSERTING"
	    MOVE BLUE TO ⊗ + (0 0 1.6) WRT BEAM_HOLE
		ON FORCE(Z WRT BEAM_HOLE) > 60 DO
		    BEGIN "MISSED AGAIN"
			STOP BLUE;
			N ← N + 1;
			GO BLUE TO SET;
		    END "MISSED AGAIN"
		ON N > 9 DO
		    BEGIN "TOO MANY MISSES, GIVE UP"
			OUTSTR("CAN'T SEEM TO GET THE BOLT IN THE HOLE");
			ABORT;
		    END "TOO MANY MISSES, GIVE UP"
		ON REACHING_DESTINATION DO SUCCEED;
	END;
**RCB** what is the planning value after a search?  need an assert? or
	will the compiler assume that the first try succeeds ... seems OK;

ASSERT BLUE = BEAM_HOLE + (0 0 3.7) WRT NBEAM_HOLE;
    COMMENT expect to have the bolt (which is 4 cm) .3 cm into the hole;

GO BLUE TO [(0 0 4):(0 0 90)] WRT ⊗
    USING FREE=(X WRT BLUE), FREE=(Y WRT BLUE)
	ON FORCE(Z WRT BLUE) > 60 DO SUCCEED;
	    COMMENT notice that there are several ways of saying "move
		forward 4cm and twist 90 degrees about the Z vector of
		the hand":
		(1) [(0 0 4):(0 0 90)] WRT ⊗
		(2) BLUE * [(0 0 4):(0 0 90)]
		    remember that the rotation (0 0 90) is done first
		(3) ⊗*[(0 0 4):(0 0 0)]*[(0 0 0):(0 0 90)];

COBEGIN "DISENGAGE"
  BEGIN "YELLOW"
    OPERATE YFINGERS WITH OPENING = 1;
    DETACH FROB FROM YELLOW;
    ATTACH FROB TO BEAM;
    MOVE YELLOW TO YPARK;
  END "YELLOW";
  BEGIN "BLUE"
    OPERATE BFINGERS WITH OPENING = 1;
    DETACH BOLT FROM BLUE;
    ATTACH BOLT TO BEAM;
    MOVE BLUE TO BPARK;
  END "BLUE";
COEND "DISENGAGE";

OUTPUT("FINISHED");
**RCB** my understanding of macros vs. library routines:
	macros are expanded by the parser ... hence their "parameters"
	consist of only strings ... Their expansion is a straight
	string substitution ... there is no way within a macro to
	do conditional expansion based upon the strings passed in
	as a parameter values ... ie. you can't do:
	    MACRO CLOSE(THE_ARM, THICKNESS) =
		⊂IFC THE_ARM = "YELLOW" THENC 
		    OPERATE YFINGERS WITH OPENING = THICKNESS;
					ELSEC
		    OPERATE BFINGERS WITH OPENING = THICKNESS; ;C ⊃

	Library routines, on the other hand, are expanded one level
	further along in the compilation process and have the symbol
	table available ... and hence NAMES and planning VALUES for
	all of the frames, vectors, etc.  The compile time IF can
	do conditional "expansion" based upon these values, the
	current attach structure, and the values of compile time
	variables (which can be any string of tokens) ... the remaining
	questions are (1) where can COMPILE IF's occur? and (2) how
	do these interact with COMPILE_TIME variables (which can only
	`expand' into tokens), but they can be used anywhere a token
	is legal?  Thus, is it possible to write the following type
	of code:
		COMPILE_TIME X, Y;
		X <≡  <USING FREE=Z>;
		Y <≡  1;
		COMPILE IF #(Y) THEN
		    BEGIN MOVE YELLOW TO Q; END
		  ELSE
		    BEGIN MOVE YELLOW TO Q
				#(X);
		    END;

		COMPILE_TIME OBJECT_1, OBJECT_2;
		ATTACH #(OBJECT_1) TO #(OBJECT_2);
	
	The only slightly irregular thing is the handling of library
	routine parameters.  In effect the parameter values are
	"names" which are substituted in for the corresponding
	parameter names.  The interpretation of whether the name
	should be left as a name (as in ATTACH X TO YELLOW) or 
	expanded into its value (as in MOVE YELLOW TO X) is
	determined by the context. Compile time variables can also be
	passed as parameters.  Thus, the following is apparently legal:
		X <≡ <USING FREE=Z>;
		MAKE_LIBRARY Q(COMPILE_TIME P);
		    BEGIN
			MOVE YELLOW TO ⊗ + (0 0 4)
			    #(#(P));
		    END;
	Which presumably would expand into:
		MOVE YELLOW TO ⊗ + (0 0 4)
		    USING FREE=Z;

	In all of this I am assuming that the syntax for macros and
	library routines is:

	a definition: DEFINE <macro name> ( <list of parameter type-name pairs> )
				= ⊂ <macro body> ⊃ ;
	a call: <macro name> ( <list of quoted strings> ) ;

	a definition: MAKE_LIBRARY <name> ( <list of parameter type-name pairs>  )
				BEGIN  <body>  END ;
	a call: <name> ( <list of parameter name-value pairs> |
			 <list of parameter values> ) ;

	With these things in mind, the following represent some
	attempts at reasonable syntax for macros (which can't expand
	conditionals) and library routines (which can pass tokens
	around)
***** EXAMPLE 3 *****

This example  employs a macro  to simplify definitions,   a  macro to
shorten  the code  for searching,    and a  library routine  to GRASP
things.   The  library  routine is  supposed  to cover  a  number  of
possibilities and provide for a  number of parameters.  Since library
routines  can be called with a subset  of their parameters filled in,
the routine's flexibility is not oppressive for those  users who just
want to do  something simple. Finally, the whole task  is made into a
library routine so  it can be  `called' (ie. expanded)  as a  subtask
from a higher level task.

A few little macros to change the conventions for defining macros

DEFINE MACRO = ⊂DEFINE⊃;
DEFINE BEGIN_MACRO = ⊂= ⊂⊃;
DEFINE END_MACRO   = ⊂⊃⊃⊃;
**RCB** How do you include a `⊃' in a macro??? can quotes be alternative
	macro delimiters ... or use SAIL's convention of ⊃⊃ within a
	macro indicates a single ⊃ ... probably a better idea

MACRO DEFINE_WRT(NEW_FRAME, MAIN_FRAME, POSITION)
  BEGIN_MACRO
    NEW_FRAME ← POSITION WRT MAIN_FRAME;
    ATTACH NEW_FRAME TO MAIN_FRAME;
  END_MACRO;

A typical call might be (assuming that quotes delimit parameter values):
	DEFINE_WRT("FROB_HOLE", "FROB", "[(5.1 2 0) : (180 0 90)]");
which would expand into:
	FROB_HOLE ← [(5.1 2 0) : (180 0 90)] WRT FROB;
	ATTACH FROB_HOLE TO FROB;


The following macro produces a string of tokens which imply a compile
time check on the value of the conditional expanded by the parameter
RIGID.  If RIGID is a "1" (ie. true) the token sequence which rigidly
attaches the new frame to the main frame is used.

MACRO DEFINE_WRT(NEW_FRAME, MAIN_FRAME, POSITION, RIGID)
  BEGIN_MACRO
    NEW_FRAME ← POSITION WRT MAIN_FRAME;
    COMPILE IF RIGID THEN ATTACH NEW_FRAME TO MAIN_FRAME RIGIDLY
		     ELSE ATTACH NEW_FRAME TO MAIN_FRAME;
  END_MACRO;


Another, more complicated macro ... one to condense a normal search

MACRO NORMAL_SEARCH(THE_ARM, INCREM, DIST_FWD, STOPPING_FORCE, NUM_TRIES)
  BEGIN_MACRO
    BEGIN COMMENT this BEGIN is part of the macro code;
	FRAME SET; SCALAR N; COMMENT N is the number of attempts;
	N ← 0;
	SET ← THE_ARM;  COMMENT save initial arm position;
	SEARCH THE_ARM
	    INCREMENT INCREM
	    NORMAL_TO Z WRT THE_ARM;
	    REPEATING
		BEGIN "INSERTION"
		    MOVE THE_ARM TO ⊗ + (0 0 DIST_FWD) WRT THE_ARM
			ON FORCE(Z WRT THE_ARM) > STOPPING_FORCE DO
			    BEGIN "MISSED AGAIN"
				STOP THE_ARM;
				N ← N + 1;
				IF N > NUM_TRIES THEN
				  BEGIN "TOO MANY MISSES"
				    OUTSTR("GIVING UP ON THE SEARCH");
				    ABORT;
				  END "TOO MANY MISSES";
				GO THE_ARM TO SET;
			    END "MISSED AGAIN"
			ON REACHING_DESTINATION DO SUCCEED;
		END "INSERTION";
	ASSERT THE_ARM = #(SET) + (0 0 (DIST_FWD - 1));
	COMMENT this changes the compiler's view to believe that the arm
		succeeds on the first attempt, BUT that it does NOT go
		as far as DIST_FWD ... possibly more realistic;
    END;
  END_MACRO;

A typical call would be:
	NORMAL_SEARCH("YELLOW", ".2", "1.6", "60", "9");

The above macro could easily be made into a library routine as follows:

MAKE_LIBRARY NORMAL_SEARCH(FRAME THE_ARM; SCALAR INCREM, DIST_FWD,
						STOPPING_FORCE, NUM_TRIES(9));
    BEGIN
	...
    END;

The corresponding call:

	NORMAL_SEARCH(YELLOW, .2, 1.6, 60, 9);

The "9" is a default value if no value is specified in the call.  Thus, by
naming the parameters the same call can be made by:

	NORMAL_SEARCH(THE_ARM=YELLOW, DIST_FWD=1.6, STOPPING_FORCE=60,
		      INCREM=.2);

      (cont)

Now for a library routine which GRASPS things ... it uses various
parameters to make various checks, to approach in a special way, etc.

MAKE_LIBRARY GRASP(COMPILE_TIME SPECIAL_DEP(NIL), A_VIA(NIL), SPECIAL_APP(NIL),
		   THE_FINGERS( YFINGERS ),
		   OPEN_AT( ON REACHING_DEPARTURE DO );
		   FRAME THE_ARM(YELLOW), OBJECT, GRASP_POINT;
		   SCALAR DEP_OPENING, APP_OPENING(15), THICKNESS(0));
**RCB** the defaults are simply tokenized and filled in if not explicitly
	assigned (ie. "DEFINED") in the call ... the predicate DEFINED(...)
	built-in so compile time checks can ask if a value was filled in
  BEGIN "GRASP"
    COMPILE IF DEFINED(DEP_OPENING) THEN
		OPERATE YFINGERS WITH OPENING=DEP_OPENING;

    MOVE YELLOW TO GRASP_POINT
	#(SPECIAL_DEP)
	#(A_VIA)
	#(SPECIAL_APP)
	#(OPEN_AT)
	    OPERATE #(THE_FINGERS) WITH OPENING=APP_OPENING;
    CENTER THE_ARM
	ON OPENING < THICKNESS DO
	    BEGIN "MISSED OBJECT"
		STOP THE_ARM;
		SCALAR FLAG;
		OPERATE THE_FINGERS WITH OPENING=APP_OPENING;
		GO THE_ARM TO (COMPILE IF DEFINED(SPECIAL_APP) THEN
			(SPECIAL_APP WRT ⊗) ELSE DEPARTURE(OBJECT));
**RCB** is DEPARTURE(OBJECT) fair?
		OUTPUT("GRASP FAILED ... TYPE A `1' TO RETRY");
		READ(FLAG);
		    COMMENT this is simply "wait for proceed";
		IF FLAG ≠ 1 THEN ABORT;
		GO THE_ARM TO OBJECT;
		CENTER THE_ARM
		    ON OPENING < THICKNESS DO ABORT;
	    END "MISSED OBJECT";

    ASSERT THE_ARM = GRASP_POINT;
    ATTACH OBJECT TO THE_ARM;
  END "GRASP";



Finally, a library routine to carry out the "bolt the frob to the beam"
task ... of course, using all of the above macros and library routines.

MAKE_LIBRARY BOLT_ON_FROB;
    BEGIN "WHOLE TASK"
	COMMENT assume that the two arms are at their park positions with
	    their hands empty;

    COBEGIN
      BEGIN "PICK UP FROB WITH YELLOW"
	GRASP(GRASP_POINT=FROB_GRASP, OBJECT=FROB, APP_OPENING=2);
	MOVE FROB_HOLE TO BEAM_HOLE + (0 0 1.3) WRT BEAM_HOLE;
	GO YELLOW TO ⊗ + (0 0 .5) WRT BEAM_HOLE
	    ON FORCE(Z WRT BEAM_HOLE) > 50 DO SUCCEED
	    ON REACHING_DESTINATION DO ABORT;
      END "PICK UP FROB WITH YELLOW;

      BEGIN "PICK UP BOLT WITH BLUE"
	GRASP(THE_ARM=BLUE, THE_FINGERS=BFINGERS, OBJECT=BOLT,
	      GRASP_POINT=BOLT, APP_OPENING=2);
      END "PICK UP BOLT WITH BLUE";
    COEND;

    MOVE BOLT TO BEAM_HOLE + (0 0 -5.3) WRT BEAM_HOLE;
    NORMAL_SEARCH(BLUE, .2, 1.6, 60, 9);
	COMMENT assume that the bolt is now in the hole;
    MOVE BLUE TO [(0 0 4):(0 0 90)] WRT ⊗
	ON FORCE(Z WRT BLUE) > 60 DO SUCCEED;

COBEGIN "DISENGAGE"
  BEGIN "YELLOW"
    OPERATE YFINGERS WITH OPENING = 1;
    DETACH FROB FROM YELLOW;
    ATTACH FROB TO BEAM;
    MOVE YELLOW TO YPARK;
  END "YELLOW";
  BEGIN "BLUE"
    OPERATE BFINGERS WITH OPENING = 1;
    DETACH BOLT FROM BLUE;
    ATTACH BOLT TO BEAM;
    MOVE BLUE TO BPARK;
  END "BLUE";
COEND "DISENGAGE";

END "WHOLE TASK";
***** EXAMPLE 4 *****

In this  version of the  task the  BLUE arm picks  up a power  driver
(which  has the  appropriate socket on  the end),   picks up  a screw
magnetically, inserts the screw in the hole, and screws in the screw.
Provisions are made  for some of the more subtle  aspects of assembly
such as freeing the FROB while trying to insert the screw in the hole
and changing the speed of the driver dynamically.

Freeing the YELLOW arm so the FROB can accommodate slightly along the
surface of the BEAM as the BLUE arm tries to insert the screw:

    MOVE BOLT TO BEAM_HOLE + (0 0 -5.3) WRT BEAM_HOLE;
	COMMENT remember that the BOLT is in the BLUE hand;
    MOVE YELLOW TO ⊗
	USING FREE=(X WRT BEAM_HOLE), FREE=(Y WRT BEAM_HOLE)
	ON DURATION > 0 DO
	    BEGIN "INSERTION"
		COMMENT notice that "DURATION > 0" is an approximation
		    to simultaneous motions;
		NORMAL_SEARCH(BLUE, .2, 1.6, 60, 9);
		    COMMENT assume that the bolt is now in the hole;
		MOVE BLUE TO [(0 0 4):(0 0 90)] WRT ⊗
		    ON FORCE(Z WRT BLUE) > 60 DO SUCCEED;
	    END "INSERTION";


Without the SEARCH this could be accomplished in "weak" synchrony.

    MOVE BOLT TO BEAM_HOLE + (0 0 -5.3) WRT BEAM_HOLE;
    MOVE {BLUE, YELLOW}
	TO {⊗ + (0 0 1.6) WRT BLUE, *}
	USING FREE = {*, (X WRT BEAM_HOLE))
	USING FREE = {*, (Y WRT BEAM_HOLE))
	ON {FORCE(Z WRT BLUE) > 60, *} DO ABORT;


But  to include  the  SEARCH this  gets  awkward.   Either  parallel,
simultaneously   beginning   blocks  should   be   allowed,   or  the
NORMAL_SEARCH macro  has  to be  rewritten  to  deal with  both  arms
simultaneously.  This type of coordination  also comes up in a number
of  other places.  For example, if you  want to operate a device (eg.
the  DRIVER)  and  move  an  arm  or  camera  "at   the  same  time."
Simultaneous blocks do, however, present some problems in timing when
one of the blocks contains "interpreters." It is not at all clear how
fast interpreters are run with respect to moving an arm.

    MOVE BOLT TO BEAM_HOLE + (0 0 -5.3) WRT BEAM_HOLE;
    SIMULTANEOUS BEGIN
      BEGIN
	MOVE YELLOW TO ⊗;
      END;
      BEGIN
	NORMAL_SEARCH(BLUE, .2, 1.6, 60, 9);
	    COMMENT assume that the bolt is now in the hole;
	MOVE BLUE TO [(0 0 4):(0 0 90)] WRT ⊗
	    ON FORCE(Z WRT BLUE) > 60 DO SUCCEED;
      END;
    SIMULTANEOUS END;


Consider the problem of screwing in a screw and checking to make sure
that it  does not bind.   If, after a short time,  the screw does not
bind, the speed of the DRIVER can be increased.  However, if  it does
bind, everything should stop and the DRIVER should be reversed to try
to unbind the screw.

SCALAR SP, FLAG;
SP ← 30;
FLAG ← 1;
WHILE FLAG DO
  BEGIN "SCREW LOOP"
    OPERATE DRIVER
	VELOCITY = SP
	ON DURATION > 0 DO
	    BEGIN "EXERT DOWNWARD FORCE"
	      MOVE BLUE TO ⊗
		USING FREE=(Z WRT BLUE)
		USING FORCE=((0 0 40) WRT BLUE)
		"BIND" ON TORQUE(Z WRT BLUE) > 80 DO
		    BEGIN
			DISABLE "CATCH_OK";
			STOP BLUE;
			STOP DRIVER;
			    COMMENT try to unbind by reversing the driver;
			SP ← -60;
			OPERATE DRIVER
			  VELOCITY = SP
			  ON DURATION > 0 DO
			    BEGIN "UPWARD FORCE"
			      MOVE BLUE TO ⊗
				USING FREE=(Z WRT BLUE)
				USING FORCE=((0 0 -40) WRT BLUE)
				"OUT_OK" ON FORCE(Z WRT BLUE)<20 DO
				  BEGIN
				    DISABLE "TOO_MUCH_TIME";
				    STOP DRIVER;
				    STOP BLUE;
				      COMMENT leave FLAG true for retry;
				  END
				"TOO_MUCH_TIME" ON DURATION>5 DO ABORT;
			    END "UPWARD FORCE";
				***** this isn't very nice ...
				I'm leaning toward simultaneous begins RCB
		    END
		"CATCH_OK" ON DURATION > 3 DO
		    BEGIN
			DISABLE "BIND";
			ENABLE "TORQUED_IN_OK";
			SP ← 60;  COMMENT maybe this should be CRITICAL;
		    END;
		"TORQUED_IN_OK" ON TORQUE(Z WRT BLUE) > 80 DO
		    BEGIN
			STOP DRIVER;
			STOP BLUE;
			FLAG ← 0;  COMMENT indicating no retry;
		    END;

	    END "EXERT DOWNWARD FORCE";

  END "SCREW LOOP";



Experimental syntax etc. used in these examples

MOVE BOLT TO BEAM_HOLE - (0 0 5.3) WRT BEAM_HOLE;
	COMMENT subtraction allowed???;

What is the statement status of a COMPILE IF ... can it be an expression?

DEFAULT THE_ARM, SPECIAL_DEP, A_VIA, SPECIAL_APP, OBJECT = NIL;
	a new construct to initial parameters possibly ... NIL means that
	there is no initialization AND this can the checked for at
	compile time to see if something other than NIL has been assigned
	If something is used and it has a NIL value the compiler should
	give and error message

ABORT ... jumps out of current program ... back to the monitor
	level ... possibly saving the world as it believes it is

ON REACHING_DESTINATION DO ... a way of distinguishing completing
	a MOVE and SUCCESS which gets you out of REPEATING etc.

Z WRT BLUE ... as a more readable way of expressing
	Z ∂ ORIENT(BLUE) ... maybe there should be a better notation

MOVE's within ON's as long as there is a STOP preceeding it ... to
	move the same arm 

MOVE BLUE TO [(0 0 4):(0 0 90)] WRT ⊗
    COMMENT how does one say move forward 4cm and twist 90 degrees
	about the approach vector of the hand? remember that the rotation
	is done first;

ASSERT THE_ARM = #(SET) + (0 0 (DIST_FWD - 1)); ... the compiler has to
	expand the macro constant DIST_FWD and do the subtraction
	to compute the actual assertion value ... can normal vectors
	contain expressions???
	may not be able to do this because SET is not a constant
	presumably this works with the #(...)

More generally ... what are the compile-time world implications of a
	SEARCH, CENTER, LOOP, ...???????